package xnj.lazydog.btcontroller.ControlViews.ControlViews;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.text.Editable;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.TextView;

import xnj.lazydog.btcontroller.ControlViews.ControlView;
import xnj.lazydog.btcontroller.ControlViews.Value;
import xnj.lazydog.btcontroller.ControlViews.ViewOptions;

public abstract class ControlElement {


    public float w_pix,h_pix,x_pix,y_pix,degree;

    public static final float SELECT_RECT_PADDING_MM = 1.2f;

    public ViewOptions options;

    Paint p;

    public Value [] linkedValues = new Value[6];
    public String[] valuesName = new String[6];
    public boolean[] data_dir_tx = new boolean[6];

    public ControlView.ToyListener toyListener;

    public boolean isPressed=false;
    public int zoomMode = 0;

    public String[] type_name = new String[]{"bool","byte","short","int","float"};


    float [] MAX_VALUES = new float[]{1,127,32767,Integer.MAX_VALUE,Float.MAX_VALUE};
    float [] MIN_VALUES = new float[]{0,-128,-32768,Integer.MIN_VALUE,-Float.MAX_VALUE};


    public float TEXT_SIZE_RATIO = 0.3f;
    public float text_height_pix;
    public float last_text_height_pix;
    public float text_y_pix;
    public float MIN_TEXT_MM = 1.5f;
    public float MAX_TEXT_MM = 5;
    public float max_text_pix;
    public float min_text_pix;

    public float edge_pix;
    public float max_edge_pix;
    public float min_edge_pix;

    public float EDGE_SIZE_RATIO = 0.1f;
    public float MAX_EDGE_MM = 1;
    public float MIN_EDGE_MM = 0.3f;

    public int THEME_TEXT_DARK_COLOR =0xff444444;

    public int THEME_WHITE =0xffffffff;
    public int THEME_GRAY =0xffaaaaaa;
    public int THEME_EDGE =0xff4eb7f0;


    public boolean settingsAfterLink = true;


    RectF rectF = new RectF();
    RectF back_rect = new RectF();

    public final float anim_k = 0.2f;
    public ControlElement(ViewOptions options) {
        this.options = options;
        p = new Paint();
        p.setFlags(Paint.FILTER_BITMAP_FLAG);
        p.setAntiAlias(true);
        p.setTextSize(40);
        p.setTextAlign(Paint.Align.CENTER);

        max_text_pix = ControlView.mm2Pix(MAX_TEXT_MM);
        min_text_pix = ControlView.mm2Pix(MIN_TEXT_MM);
        max_edge_pix = ControlView.mm2Pix(MAX_EDGE_MM);
        min_edge_pix = ControlView.mm2Pix(MIN_EDGE_MM);
    }

    void initLimitedEdit(final  EditText editText,final int min,final int max)
    {
        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

                int number;
                if(s.toString().equals("")||s.toString().equals("-"))
                    return;
                try {
                    number = Integer.parseInt(s.toString());
                }catch (NumberFormatException e)
                {
                    number = 0;
                    editText.setText("");
                    editText.setSelection(0);
                }
                if(number>max)
                {
                    String v_str;
                    v_str = ""+max;
                    editText.setText(v_str);
                    editText.setSelection(v_str.length());

                }
                if(number<min)
                {
                    String v_str;
                    v_str = ""+min;
                    editText.setText(v_str);
                    editText.setSelection(v_str.length());
                }
            }
            @Override
            public void afterTextChanged(Editable s) {
            }
        });
    }
    void initLimitedEdit(final EditText editText, final TextView warn, final int type)
    {

        final float max = MAX_VALUES[type];
        final float min = MIN_VALUES[type];

        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

                float number;
                if(s.toString().equals("")||s.toString().equals("-"))
                    return;
                try {
                    number = Float.parseFloat(s.toString());
                }catch (NumberFormatException e)
                {
                    number = 0;
                    editText.setText("");
                    editText.setSelection(0);
                }
                if(number>max)
                {
                    String v_str;
                    if(type==4)
                        v_str = ""+max;
                    else
                        v_str = ""+((int)max);
                    editText.setText(v_str);
                    editText.setSelection(v_str.length());
                    if(warn!=null)
                    ControlView.bigSmall(warn);
                }
                if(number<min)
                {
                    String v_str;
                    if(type==4)
                        v_str = ""+min;
                    else
                        v_str = ""+((int)min);
                    editText.setText(v_str);
                    editText.setSelection(v_str.length());
                    if(warn!=null)
                    ControlView.bigSmall(warn);
                }
            }
            @Override
            public void afterTextChanged(Editable s) {
            }
        });
    }


    void initLimitedEdit(final EditText editText,final float min,final float max,final int type)
    {


        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

                float number;
                if(s.toString().equals("")||s.toString().equals("-"))
                    return;
                try {
                    number = Float.parseFloat(s.toString());
                }catch (NumberFormatException e)
                {
                    number = 0;
                    editText.setText("");
                    editText.setSelection(0);
                }
                if(number>max)
                {
                    String v_str;
                    if(type==4)
                        v_str = ""+max;
                    else
                        v_str = ""+((int)max);
                    editText.setText(v_str);
                    editText.setSelection(v_str.length());

                }
                if(number<min)
                {
                    String v_str;
                    if(type==4)
                        v_str = ""+min;
                    else
                        v_str = ""+((int)min);
                    editText.setText(v_str);
                    editText.setSelection(v_str.length());

                }
            }
            @Override
            public void afterTextChanged(Editable s) {
            }
        });
    }


    public Value getNumber(String s)
    {
        Value value;
        if(s==null||s.equals("")||s.equals("-")) {
            //return false;
            value = new Value(0);
        }else
        {
            try {
                if (s.contains(".")) {
                    value = new Value(4);
                    value.set(Float.parseFloat(s));
                } else {
                    value = new Value(3);
                    value.set(Integer.parseInt(s));
                }
            }catch (NumberFormatException e)
            {
                value = new Value(0);
            }
        }
        return value;
    }

    public int getNumber(String s,int def)
    {
        int number;
        if(s==null)
            return def;
        try
        {
            number = Integer.parseInt(s);
        }catch (NumberFormatException e)
        {
            return def;
        }
        return number;
    }

    public void showSettingsDialog(Context context)
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);

        builder.setTitle("Element").setPositiveButton("yes", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        }).create().show();
    }

    void triggerDataEvent()
    {
        if(toyListener!=null)
            toyListener.onToyValueChanged();
    }

    public static ControlElement newInstance(ViewOptions op)
    {
        ControlElement element;
        switch (op.uiType)
        {
            case ViewOptions.UI_TYPE_TEXT:
                element = new ControlText(op);
                break;
            case ViewOptions.UI_TYPE_EDIT_TEXT:
                element = new ControlEditText(op);
                break;
            case  ViewOptions.UI_TYPE_SWITCH:
                element = new ControlSwitch(op);
                break;
            case  ViewOptions.UI_TYPE_BUTTON:
                element = new ControlButton(op);
                break;
            case  ViewOptions.UI_TYPE_VALUE_BAR:
                element = new ControlValueBar(op);
                break;
            case  ViewOptions.UI_TYPE_VALUE_DRAG_BAR:
                element = new ControlValueDragBar(op);
                break;
            case  ViewOptions.UI_TYPE_2AXIS_STICK:
                element = new Control2AxisStick(op);
                break;
            case  ViewOptions.UI_TYPE_2AXIS_PLOT:
                element = new Control2AxisPlot(op);
                break;
            case  ViewOptions.UI_TYPE_PLOT:
                element = new ControlPlot(op);
                break;
            case  ViewOptions.UI_TYPE_VALUE_BUTTON:
                element = new ControlValueButton(op);
                break;
                default:
                    element = new ControlText(op);
        }
        element.options = op;
        return element;
    }

    public void setScale(int x,int y)
    {
        isNewLayoutValue = true;
        options.w = x;
        options.h = y;
    }

    public void setPositionImm(int x_mm,int y_mm)
    {
        isNewLayoutValue = true;
        x_pix = (ControlView.mm2Pix(x_mm));
        y_pix = (ControlView.mm2Pix(y_mm));
    }

    public void setPosition(int x,int y)
    {
        isNewLayoutValue = true;
        options.x = x;
        options.y = y;
    }
    public void setRotation(int deg)
    {
        isNewLayoutValue = true;
        options.deg = deg;
    }

    float k=0.2f;
    boolean isNewLayoutValue = true;
    float d_x,d_y,d_w,d_h,d_d;

    float getRoundDelta(float delta)
    {
        while (delta>180)
            delta-=360;
        while (delta<-180)
            delta+=360;
        return delta;
    }

    public void update()
    {
        if(isNewLayoutValue)
        {
            d_x = (ControlView.mm2Pix(options.x)-x_pix);
            d_y = (ControlView.mm2Pix(options.y)-y_pix);
            d_w = (ControlView.mm2Pix(options.w)-w_pix);
            d_h = (ControlView.mm2Pix(options.h)-h_pix);
            d_d = getRoundDelta(options.deg-degree);
            x_pix += d_x*k;
            y_pix += d_y*k;
            w_pix += d_w*k;
            h_pix += d_h*k;
            degree += d_d*k;
            if( Math.abs(d_x)+Math.abs(d_y)+Math.abs(d_w)+Math.abs(d_h)+Math.abs(d_d)*10<0.1f)
            {
                isNewLayoutValue = false;
            }
            onSizeChanged();
        }
    }


    public void onSizeChanged()
    {

    }

    public void updatePix()
    {
        isNewLayoutValue = true;
        d_x = (ControlView.mm2Pix(options.x)-x_pix);
        d_y = (ControlView.mm2Pix(options.y)-y_pix);
        d_w = (ControlView.mm2Pix(options.w)-w_pix);
        d_h = (ControlView.mm2Pix(options.h)-h_pix);
        d_d = getRoundDelta(options.deg-degree);
        x_pix += d_x;
        y_pix += d_y;
        w_pix += d_w;
        h_pix += d_h;
        degree += d_d;
        onSizeChanged();
    }

    private static final String TAG = "ControlElement";

    public void draw(Canvas canvas)
    {

        p.setARGB(255,55,155,205);
        canvas.drawRect(-w_pix*0.5f,-h_pix*0.5f,w_pix*0.5f,h_pix*0.5f,p);
        p.setARGB(255,255,255,255);
        canvas.drawText(""+options.uiType,0,20,p);

    }


    float ax,ay;
    public float rx,ry;
    float dx,dy,ddx,ddy;
    float margin_pix;
    public boolean isInArea(float ax,float ay,boolean hasMargin)
    {
        boolean isIn = false;
        this.ax = ax;
        this.ay = ay;

        if(hasMargin)
            margin_pix = ControlView.mm2Pix(ControlElement.SELECT_RECT_PADDING_MM);
        else
            margin_pix = 0;
        //// 求出位置差
        dx = ax-x_pix;
        dy = ay-y_pix;

        //// 旋转变换
        ddx = dx*(float)Math.cos(Math.toRadians(-degree))-dy*(float) Math.sin(Math.toRadians(-degree));
        ddy = dy*(float)Math.cos(Math.toRadians(-degree))+dx*(float) Math.sin(Math.toRadians(-degree));


        if(Math.abs(ddx)<w_pix*0.5f+margin_pix&&Math.abs(ddy)<h_pix*0.5f+margin_pix)
        {
            rx = ddx/w_pix+0.5f;
            ry = ddy/h_pix+0.5f;
            isIn = true;
        }else
        {
            rx = ddx/w_pix+0.5f;
            ry = ddy/h_pix+0.5f;
//            rx = -1;
//            ry = -1;
        }
        return isIn;
    }


    public int getMiddleColor(int c1,int c2,float p)
    {
        float a,r,g,b;

        a = Color.alpha(c1)+(Color.alpha(c2)-Color.alpha(c1)*1.0f)*p;
        r = Color.red(c1)+(Color.red(c2)-Color.red(c1)*1.0f)*p;
        g = Color.green(c1)+(Color.green(c2)-Color.green(c1)*1.0f)*p;
        b = Color.blue(c1)+(Color.blue(c2)-Color.blue(c1)*1.0f)*p;

        if(a>255)
            a=255;
        if(a<0)
            a = 0;

        if(r<0)
            r = 0;
        if(g<0)
            g = 0;
        if(b<0)
            b = 0;
        if(r>255)
            r = 255;
        if(g>255)
            g = 255;
        if(b>255)
            b = 255;

        return Color.argb((int)a,(int)r,(int)g,(int)b);
    }


    public abstract void clicked(Context context);


    public abstract void dragged();


    public abstract void released();


    public abstract void pressed();


    public abstract void zoomed(float sx,float sy);

    public void zoom_started()
    {

    }

    public void onRxData()
    {


    }
}
